{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "collapsed": true,
    "executionInfo": {
     "elapsed": 8016,
     "status": "ok",
     "timestamp": 1729277605504,
     "user": {
      "displayName": "Hoyt Long",
      "userId": "07552314465936486693"
     },
     "user_tz": 300
    },
    "id": "ssKxHWSOU6Si",
    "jupyter": {
     "outputs_hidden": true
    },
    "outputId": "74a14043-f11d-4b3d-e6f0-3bb8bb6e206c"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting anthropic\n",
      "  Downloading anthropic-0.36.2-py3-none-any.whl.metadata (21 kB)\n",
      "Requirement already satisfied: anyio<5,>=3.5.0 in /usr/local/lib/python3.10/dist-packages (from anthropic) (3.7.1)\n",
      "Requirement already satisfied: distro<2,>=1.7.0 in /usr/lib/python3/dist-packages (from anthropic) (1.7.0)\n",
      "Collecting httpx<1,>=0.23.0 (from anthropic)\n",
      "  Downloading httpx-0.27.2-py3-none-any.whl.metadata (7.1 kB)\n",
      "Collecting jiter<1,>=0.4.0 (from anthropic)\n",
      "  Downloading jiter-0.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (5.2 kB)\n",
      "Requirement already satisfied: pydantic<3,>=1.9.0 in /usr/local/lib/python3.10/dist-packages (from anthropic) (2.9.2)\n",
      "Requirement already satisfied: sniffio in /usr/local/lib/python3.10/dist-packages (from anthropic) (1.3.1)\n",
      "Requirement already satisfied: tokenizers>=0.13.0 in /usr/local/lib/python3.10/dist-packages (from anthropic) (0.19.1)\n",
      "Requirement already satisfied: typing-extensions<5,>=4.7 in /usr/local/lib/python3.10/dist-packages (from anthropic) (4.12.2)\n",
      "Requirement already satisfied: idna>=2.8 in /usr/local/lib/python3.10/dist-packages (from anyio<5,>=3.5.0->anthropic) (3.10)\n",
      "Requirement already satisfied: exceptiongroup in /usr/local/lib/python3.10/dist-packages (from anyio<5,>=3.5.0->anthropic) (1.2.2)\n",
      "Requirement already satisfied: certifi in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->anthropic) (2024.8.30)\n",
      "Collecting httpcore==1.* (from httpx<1,>=0.23.0->anthropic)\n",
      "  Downloading httpcore-1.0.6-py3-none-any.whl.metadata (21 kB)\n",
      "Collecting h11<0.15,>=0.13 (from httpcore==1.*->httpx<1,>=0.23.0->anthropic)\n",
      "  Downloading h11-0.14.0-py3-none-any.whl.metadata (8.2 kB)\n",
      "Requirement already satisfied: annotated-types>=0.6.0 in /usr/local/lib/python3.10/dist-packages (from pydantic<3,>=1.9.0->anthropic) (0.7.0)\n",
      "Requirement already satisfied: pydantic-core==2.23.4 in /usr/local/lib/python3.10/dist-packages (from pydantic<3,>=1.9.0->anthropic) (2.23.4)\n",
      "Requirement already satisfied: huggingface-hub<1.0,>=0.16.4 in /usr/local/lib/python3.10/dist-packages (from tokenizers>=0.13.0->anthropic) (0.24.7)\n",
      "Requirement already satisfied: filelock in /usr/local/lib/python3.10/dist-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers>=0.13.0->anthropic) (3.16.1)\n",
      "Requirement already satisfied: fsspec>=2023.5.0 in /usr/local/lib/python3.10/dist-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers>=0.13.0->anthropic) (2024.6.1)\n",
      "Requirement already satisfied: packaging>=20.9 in /usr/local/lib/python3.10/dist-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers>=0.13.0->anthropic) (24.1)\n",
      "Requirement already satisfied: pyyaml>=5.1 in /usr/local/lib/python3.10/dist-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers>=0.13.0->anthropic) (6.0.2)\n",
      "Requirement already satisfied: requests in /usr/local/lib/python3.10/dist-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers>=0.13.0->anthropic) (2.32.3)\n",
      "Requirement already satisfied: tqdm>=4.42.1 in /usr/local/lib/python3.10/dist-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers>=0.13.0->anthropic) (4.66.5)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/dist-packages (from requests->huggingface-hub<1.0,>=0.16.4->tokenizers>=0.13.0->anthropic) (3.4.0)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests->huggingface-hub<1.0,>=0.16.4->tokenizers>=0.13.0->anthropic) (2.2.3)\n",
      "Downloading anthropic-0.36.2-py3-none-any.whl (939 kB)\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m939.6/939.6 kB\u001b[0m \u001b[31m14.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hDownloading httpx-0.27.2-py3-none-any.whl (76 kB)\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m76.4/76.4 kB\u001b[0m \u001b[31m5.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hDownloading httpcore-1.0.6-py3-none-any.whl (78 kB)\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m78.0/78.0 kB\u001b[0m \u001b[31m5.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hDownloading jiter-0.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (325 kB)\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m325.2/325.2 kB\u001b[0m \u001b[31m23.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hDownloading h11-0.14.0-py3-none-any.whl (58 kB)\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m4.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hInstalling collected packages: jiter, h11, httpcore, httpx, anthropic\n",
      "Successfully installed anthropic-0.36.2 h11-0.14.0 httpcore-1.0.6 httpx-0.27.2 jiter-0.6.1\n"
     ]
    }
   ],
   "source": [
    "#load necessary libraries\n",
    "!pip install anthropic\n",
    "\n",
    "from google.colab import userdata\n",
    "import anthropic\n",
    "\n",
    "# Set up the Anthropic API client\n",
    "api_key = userdata.get('Anthropic_API_KEY')\n",
    "client = anthropic.Client(api_key=api_key)\n",
    "\n",
    "def prompt_1(passage):\n",
    "    # Prompt 1\n",
    "    system_prompt = \"You are an experienced writer and teacher of creative writing who has read most of the major creative writing handbooks published over the last fifty years. You are especially good at giving advice on character development in fiction. Character development refers to any aspect of how the author imagines, describes, represents, and enacts the character(s).\"\n",
    "    user_prompt = \"Hi! I'm working on a story and would like some advice on how well I'm handling my character development. Can you identify 2 specific aspects or techniques of character development that I'm using in the passage? For each, please offer some general advice about it's importance for writing good fiction, like what I might find in a creative writing guide. Don't reference my own story in your response. Please format your response using the following XML-like tags: <technique1>, <advice1>, <technique2>, and <advice2>. Okay, here's what I've written so far: \"\n",
    "\n",
    "    message = client.messages.create(\n",
    "        model=\"claude-3-opus-20240229\",\n",
    "        max_tokens=4000,\n",
    "        temperature=1,\n",
    "        system=system_prompt,\n",
    "        messages=[\n",
    "          {\n",
    "            \"role\": \"user\",\n",
    "            \"content\": [\n",
    "              {\n",
    "                \"type\": \"text\",\n",
    "                \"text\": user_prompt + passage\n",
    "              }\n",
    "            ]\n",
    "          }\n",
    "        ]\n",
    "      )\n",
    "\n",
    "  # Extract the assistant's response\n",
    "    return message.content[0].text\n",
    "\n",
    "def prompt_2(passage):\n",
    "  #prompt 2\n",
    "  system_prompt = \"You are an experienced writer and teacher of creative writing who has read most of the major creative writing handbooks published over the last fifty years. You are especially good at giving advice on character development in fiction. Character development refers to any aspect of how the author imagines, describes, represents, and enacts the character(s).\"\n",
    "  user_prompt = \"Hi! I'm working on a story and would like some advice on how well I'm handling my character development. Can you rank this passage on a scale of 1 to 10? 1 would mean that I've done a really poor job of characterization, and show little skill at using even the most basic techniques. 10 means the character development is very skilled, showing a high level of fluency with characterization techniques. Just give me a score. Please be as honest as possible in your assessment. Don't offer any written justification yet. Format the ranking using the following XML-like tag: <score>. Here's what I've written so far: \"\n",
    "\n",
    "  message = client.messages.create(\n",
    "        model=\"claude-3-opus-20240229\",\n",
    "        max_tokens=2000,\n",
    "        temperature=1,\n",
    "        system=system_prompt,\n",
    "        messages=[\n",
    "          {\n",
    "            \"role\": \"user\",\n",
    "            \"content\": [\n",
    "              {\n",
    "                \"type\": \"text\",\n",
    "                \"text\": user_prompt + passage\n",
    "              }\n",
    "            ]\n",
    "          }\n",
    "        ]\n",
    "      )\n",
    "\n",
    "  # Extract the assistant's response\n",
    "  return message.content[0].text\n",
    "\n",
    "def prompt_3(passage, score):\n",
    "  #prompt 3\n",
    "  system_prompt = \"You are an experienced writer and teacher of creative writing who has read most of the major creative writing handbooks published over the last fifty years. You are especially good at giving advice on character development in fiction. Character development refers to any aspect of how the author imagines, describes, represents, and enacts the character(s).\"\n",
    "  user_prompt = \"I'm a writer working on a new story and want your thoughts on how I'm handling my character development. I previously showed you this passage: \" + passage + \"When I asked you to rank the quality of characterization from 1 to 10, you gave it the following score: \" + score + \"Now I want to know if you have any practical lessons for what I can do as a writer to give my characters complexity and depth? Not on the page, but in my creative process or in how I observe people in the world. Please recommend one exercise I can do and any words of wisdom based on your reaction to the quality of my writing. Please be honest with me. And please format your response using the following XML-like tags: <exercise> and <wisdom>.\"\n",
    "\n",
    "  message = client.messages.create(\n",
    "    model=\"claude-3-opus-20240229\",\n",
    "    max_tokens=4000,\n",
    "    temperature=1,\n",
    "    system=system_prompt,\n",
    "      messages=[\n",
    "        {\n",
    "          \"role\": \"user\",\n",
    "          \"content\": [\n",
    "            {\n",
    "              \"type\": \"text\",\n",
    "              \"text\": user_prompt\n",
    "            }\n",
    "          ]\n",
    "        }\n",
    "      ]\n",
    "    )\n",
    "\n",
    "  # Extract the assistant's response\n",
    "  return message.content[0].text\n",
    "\n",
    "def prompt_4(passage, observations):\n",
    "  #prompt 4\n",
    "  system_prompt = \"You are an experienced writer and teacher of creative writing who has read most of the major creative writing handbooks published over the last fifty years. You are especially good at giving advice on character development in fiction. Character development refers to any aspect of how the author imagines, describes, represents, and enacts the character(s).\"\n",
    "  user_prompt = \"I'm a writer working on a story and you previously observed the following about a passage I showed you: \" + observations + \" What's the first and best piece of actionable advice you think I need to improve my characterization? Do not revise or rewrite the passage. Just give me one actionable item and a written explanation in 300 words or less. If you know of a relevant example from a novel or published story, please share it. Please format your response using the following XML-like tags: <advice_label>, <advice>, <example_work>, and <example>. Here's the passage I showed you before: \"\n",
    "\n",
    "  message = client.messages.create(\n",
    "  model=\"claude-3-opus-20240229\",\n",
    "  max_tokens=4000,\n",
    "  temperature=1,\n",
    "  system=system_prompt,\n",
    "    messages=[\n",
    "      {\n",
    "        \"role\": \"user\",\n",
    "        \"content\": [\n",
    "          {\n",
    "            \"type\": \"text\",\n",
    "            \"text\": user_prompt + passage\n",
    "          }\n",
    "        ]\n",
    "      }\n",
    "    ]\n",
    "  )\n",
    "\n",
    "  # Extract the assistant's response\n",
    "  return message.content[0].text\n",
    "\n",
    "def prompt_5(passage, feedback):\n",
    "  #prompt 5\n",
    "  system_prompt = \"You are an experienced writer and teacher of creative writing who has read most of the major creative writing handbooks published over the last fifty years. You are especially good at giving advice on character development in fiction. Character development refers to any aspect of how the author imagines, describes, represents, and enacts the character(s).\"\n",
    "  user_prompt = \"I'm a writer working on a story and you previously gave me the following feedback about a passage I showed you: \" + feedback + \"Using this feedback, can you rewrite the passage for me? Do not change things that you think are working well. And please just return the revised passage, without additional explanation, using the following XML-like tags: <revision>. Here's the passage again: \"\n",
    "\n",
    "  message = client.messages.create(\n",
    "    model=\"claude-3-opus-20240229\",\n",
    "    max_tokens=4000,\n",
    "    temperature=1,\n",
    "    system=system_prompt,\n",
    "      messages=[\n",
    "        {\n",
    "          \"role\": \"user\",\n",
    "          \"content\": [\n",
    "            {\n",
    "              \"type\": \"text\",\n",
    "              \"text\": user_prompt + passage\n",
    "            }\n",
    "          ]\n",
    "        }\n",
    "      ]\n",
    "    )\n",
    "\n",
    "  # Extract the assistant's response\n",
    "  return message.content[0].text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 6386895,
     "status": "ok",
     "timestamp": 1729307174938,
     "user": {
      "displayName": "Hoyt Long",
      "userId": "07552314465936486693"
     },
     "user_tz": 300
    },
    "id": "2NCEc9ZoUncg",
    "outputId": "b444c478-387b-4c1c-b175-2f62740342d0"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": []
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import random\n",
    "import time\n",
    "\n",
    "#import dataframe containing all the passages\n",
    "#need to load this csv file into Colab\n",
    "df = pd.read_csv(\"/content/drive/MyDrive/AI_Instructor/MASTER_META.csv\")\n",
    "\n",
    "# Generate 10 random numbers between 1 and 800\n",
    "#rows_to_filter = random.sample(range(1, 801), 10)\n",
    "# Filter the DataFrame based on the random numbers\n",
    "#df = df.iloc[rows_to_filter]\n",
    "\n",
    "# Create new columns in the DataFrame\n",
    "df[\"OBSERVATIONS\"] = \"\"\n",
    "df[\"SCORE\"] = \"\"\n",
    "df[\"REACTION\"] = \"\"\n",
    "df[\"FEEDBACK\"] = \"\"\n",
    "df[\"REVISED_PASSAGE\"] = \"\"\n",
    "\n",
    "#loop through dataframe and feed passages into prompts\n",
    "for k in df.index:\n",
    "  #get the passage\n",
    "  passage = df.loc[k, \"PASSAGE\"]\n",
    "\n",
    "  #move through prompts\n",
    "  #insert a .12 second pause between calls to API (we have 500 RPM limit)\n",
    "  observations = prompt_1(passage)\n",
    "  time.sleep(.12)\n",
    "  score = prompt_2(passage)\n",
    "  time.sleep(.12)\n",
    "  reaction = prompt_3(passage, score)\n",
    "  time.sleep(.12)\n",
    "  feedback = prompt_4(passage, observations)\n",
    "  time.sleep(.12)\n",
    "  revised_passage = prompt_5(passage, feedback)\n",
    "  time.sleep(.12)\n",
    "\n",
    "  df.loc[k, \"OBSERVATIONS\"] = observations\n",
    "  df.loc[k, \"SCORE\"] = score\n",
    "  df.loc[k, \"REACTION\"] = reaction\n",
    "  df.loc[k, \"FEEDBACK\"] = feedback\n",
    "  df.loc[k, \"REVISED_PASSAGE\"] = revised_passage\n",
    "\n",
    "  #we might also want to save output text in case we hit a runtime error (or just write .csv to disk at certain intervals?)\n",
    "  print(\"Item: \" + str(k), end=\"\\r\")\n",
    "\n",
    "# save the dataframe to disk\n",
    "df.to_csv('/content/drive/MyDrive/AI_Instructor/OPUS_OUTPUT.csv', index=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "collapsed": true,
    "executionInfo": {
     "elapsed": 249,
     "status": "ok",
     "timestamp": 1729125359304,
     "user": {
      "displayName": "Hoyt Long",
      "userId": "07552314465936486693"
     },
     "user_tz": 300
    },
    "id": "UZtJzY8eF7wy",
    "jupyter": {
     "outputs_hidden": true
    },
    "outputId": "ce4cef01-0f13-401c-86d2-23801cbeafd4"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(799, 14)"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# save the dataframe to disk\n",
    "#df.to_csv('MASTER_META_OUTPUT.csv', index=False)\n",
    "df.shape"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.19"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
